local USABLE_COLOR         = {1.0, 1.0, 1.0}
local OOM_COLOR            = {0.5, 0.5, 1.0}
local OUT_OF_RANGE_COLOR   = {1.0, 0.5, 0.5}
local UNUSABLE_COLOR       = {0.5, 0.5, 0.5}
local COOLDOWN_MARGIN      = 1
local FRAME_MARGIN         = 10
local COOLDOWN_SIZE        = 30

SpyCooldown = Spy.NewFrameType("SpyCooldown", "BUTTON")

SpyCooldownEvents = {}
SpyCooldownHandlers = {}

SpyCooldownGroup = {}
SpyCooldownGroupHandlers = {}
SpyCooldownGroupEvents = {}

-------------------------------------------------------------------------------
function SpyCooldown:UpdateUsable()
   local bUsable, bNoMana = IsUsableSpell(self.spell)
   local color
   
   if self.outOfRange then
      color = OUT_OF_RANGE_COLOR
   else
      if bUsable then
         color = USABLE_COLOR
      elseif bNoMana then
         color = OOM_COLOR
      else
         color = UNUSABLE_COLOR
      end
   end
   
   self.tex:SetVertexColor(unpack(color))
end

function SpyCooldown:UpdateCooldown()
   local start, duration, enable = GetSpellCooldown(self.spell)
	
   if start > 0 and duration > 0 and enable > 0 then
		self.cooldown:SetCooldown(start, duration)
		self.cooldown:Show()
      self.destTime = (start + duration)
      if duration > 1.9 then
         if duration > 10 then
            self.alert = true
         end
         self.time:Show()
      else
         self.time:Hide()
      end
	else
      self.cooldown:Hide()
      self.time:Hide()
   end
end

function SpyCooldown:Update()
   self:UpdateUsable()
   self:UpdateCooldown()
   self.rangeTimer = -1
   --self:UpdateCount()
end

function SpyCooldown:SetTooltip()
   GameTooltip:SetOwner(self, ANCHOR_BOTTOMRIGHT)
   GameTooltip:SetSpell(self.spellID, BOOKTYPE_SPELL)
end

-------------------------------------------------------------------------------
function SpyCooldownHandlers:OnUpdate(elapsed)
   assert(self ~= SpyCooldownHandlers)
   
   if self.rangeTimer then
      self.rangeTimer = self.rangeTimer - elapsed
      if self.rangeTimer <= 0 then
         local valid = IsSpellInRange(self.spell, "target")
         self.outOfRange = (valid == 0)
         self:UpdateUsable()
         rangeTimer = TOOLTIP_UPDATE_TIME
      end
   end
   
   if self.time:IsShown() then
      if GetTime() < self.destTime then
         local timeLeft = self.destTime - GetTime()
         self.time:SetFormattedText(SecondsToTimeAbbrev(timeLeft))
         self.time:Show()
      else
         self.time:Hide()
         self.tex:SetVertexColor(1, 1, 1)
         if self.alert then
            PlaySound('PVPENTERQUEUE')
            local text = "Spell ready: " .. self.spell
            DEFAULT_CHAT_FRAME:AddMessage(text, 1, 0.8, 0.3)
            if SpySCT and not SpyDB.bNoSCTReadyMessages then
               SpySCT.ScrollMessage(self.spell .. ' is ready')
            end
            self.alert = nil
         end
      end
   end
end

local lineAdded = false
local function OnTooltipSetSpell(tooltip, ...)
   if not lineAdded then
      local name, rank, id = tooltip:GetSpell()
      local text1 = 'ID: ' .. id
      local text2 = ' '
      if rank ~= '' then
         text2 = rank
      end
      tooltip:AddDoubleLine(text2, text1, 0.6, 0.6, 0.6, 0.2, 0.2, 1.0)
      lineAdded = true
   end
end

local function OnTooltipCleared(tooltip, ...)
   lineAdded = false
end

GameTooltip:HookScript("OnTooltipSetSpell", OnTooltipSetSpell)
GameTooltip:HookScript("OnTooltipCleared", OnTooltipCleared)

function SpyCooldownHandlers:OnEnter()
   self:SetTooltip()
   self.UpdateTooltip = SpyCooldown.SetTooltip
end

function SpyCooldownHandlers:OnLeave()
   GameTooltip:Hide()
   self.UpdateTooltip = nil
end

-------------------------------------------------------------------------------
function SpyCooldownEvents:PLAYER_ENTERING_WORLD()
   self:Update()
end

function SpyCooldownEvents:PLAYER_TARGET_CHANGED()
   self.rangeTimer = -1
end

function SpyCooldownEvents:ACTIONBAR_UPDATE_USABLE()
   self:UpdateUsable()
end

function SpyCooldownEvents:ACTIONBAR_UPDATE_COOLDOWN()
   self:UpdateCooldown()
end

-- function SpyCooldownEvents:SPELL_UPDATE_COOLDOWN()
   -- self:UpdateCooldown()
-- end

-- function SpyCooldownEvents:SPELL_UPDATE_USABLE()
   -- self:UpdateUsable()
-- end

-------------------------------------------------------------------------------
function SpyCooldown.Create(parent, id, spell)
   local name, rank, icon, cost, bFunnel, powtype, casttime, rmin, rmax = GetSpellInfo(spell)
   assert(name)

   local self = Spy.CreateFrame("SpyCooldown", "$parent_Button"..id, parent, "SecureUnitButtonTemplate")
   
   self.spell = GetHighestRankSpellName(spell)
   self.spellID = GetSpellID(self.spell)
   assert(self.spellID)

   self:SetWidth(COOLDOWN_SIZE)
   self:SetHeight(COOLDOWN_SIZE)
   self:RegisterForClicks("LeftButtonUp", "MiddleButtonUp", "RightButtonUp", "Button4Up", "Button5Up")
   self:EnableMouse(true)
   self:SetAttribute("type1", "spell")
   self:SetAttribute("type2", "spell")
   self:SetAttribute("spell1", self.spell)
   -- self:SetAttribute("unit", "target")
	self:SetAttribute("checkselfcast", true);
	self:SetAttribute("checkfocuscast", true);
	self:SetAttribute("useparent-unit", true);
   self:Show()

   self.tex = self:CreateTexture()
   self.tex:SetAllPoints()
   self.tex:SetTexture(icon)
   
   self.cooldown = CreateFrame("COOLDOWN", "$parent_Cooldown", self)
   self.cooldown:SetAllPoints()
   self.cooldown:SetAlpha(1.0)
   self.cooldown:Show()
   
   self.time = self.cooldown:CreateFontString("$parent_Text", "OVERLAY", "SpyCooldownFont")
   self.time:SetAllPoints()
   self.time:SetJustifyH("CENTER")
   self.time:SetJustifyV("CENTER")
   self.time:SetVertexColor(1, 1, 1)
   
   Spy.RegisterAll(self, SpyCooldownEvents, SpyCooldownHandlers)
   return self
end
  
-------------------------------------------------------------------------------
function SpyCooldownGroup:CreateActionButton(spellName)
   if not GetSpellInfo(spellName) then return end

   local id = #self.buttons
   local b = SpyCooldown.Create(self, id, spellName)
   table.insert(self.buttons, b)

   local left = FRAME_MARGIN + id * (COOLDOWN_SIZE + COOLDOWN_MARGIN)
   b:SetPoint("TOPLEFT", left, -FRAME_MARGIN)
   self:SetWidth(left + COOLDOWN_SIZE + FRAME_MARGIN)
end

function SpyCooldownGroup:Init(spells)
   for i, v in ipairs(spells) do
      self:CreateActionButton(v)
   end
   self:Update()
end

function SpyCooldownGroup:Update()
   for i, b in ipairs(self.buttons) do
      b:Update()
   end
end

-------------------------------------------------------------------------------
function SpyCooldownGroupHandlers:OnMouseWheel(dir)
   local scale = self:GetScale()
   scale = max(0.1, min(4.0, scale + (dir * 0.1)))
   self:SetScale(scale)
end

function Spy.CreateCooldownGroup(name, spells)
   local f = Spy.CreateManagedFrame("FRAME", name)
   Spy.ManageFrame(f)
   f:SetWidth(4)
   f:SetHeight(COOLDOWN_SIZE + FRAME_MARGIN*2)
   f:EnableMouseWheel(true)
   f.buttons = {}
   Spy.RegisterHandlers(f, SpyCooldownGroupHandlers)
   Spy.RegisterMethods(f, SpyCooldownGroup)
   if spells and type(spells) == "table" then
      f:Init(spells)
   end
   return f
end

-------------------------------------------------------------------------------
Spy.CooldownGroups = {}

local bInitialized = false
function Spy.InitCooldowns()
   if SpyDB.bNoCooldowns then return true end
   local _, class = UnitClass("player")
   if not bInitialized and class=="PALADIN" then
      for k, v in pairs(Spy.CDGroups) do
         local group = Spy.CreateCooldownGroup("SpyCooldown_"..k, v)
         Spy.CooldownGroups[group] = group
      end
      bInitialized = true
      return true
   end
end

-- FIXME
--AddEventListener("PLAYER_ENTERING_WORLD", Spy.InitCooldowns)

-------------------------------------------------------------------------------
-- Spy.BuffTimers = {}

-- local frame = CreateFrame('FRAME')
-- local events = {}

-- function events:UNIT_AURA(unit)
   -- if unit=='player' then
      -- local buffs, i = { }, 1;
      -- local buff = UnitBuff("player", i);
      -- while buff do
        -- buffs[#buffs + 1] = buff;
        -- i = i + 1;
        -- buff = UnitBuff("player", i);
      -- end;
      -- if #buffs < 1 then
        -- buffs = "You have no buffs";
      -- else
        -- buffs[1] = "You're buffed with: "..buffs[1];
        -- buffs = table.concat(buffs, ", ");
      -- end;
      -- DEFAULT_CHAT_FRAME:AddMessage(buffs);
   -- end
-- end

-- -- function events:UNIT_SPELLCAST_SUCCEEDED(unit, spell, rank)
   -- -- if unit=='player' then
      -- -- if spell=='
   -- -- end
-- -- end

-- RegisterEvents(frame, events)

